// -----------------------------------------------------------------------
//  <copyright file="EntitySeederBase.cs" company="LiuliuSoft">
//      Copyright (c) 2022-2024 DaprPlus. All rights reserved.
//  </copyright>
//  <site>https://dapr.plus</site>
//  <last-editor>郭明锋</last-editor>
//  <last-date>2024/12/6 16:39:28</last-date>
// -----------------------------------------------------------------------

namespace DaprPlus.Domain.Entity;

public abstract class EntitySeederBase<TEntity>(IServiceProvider provider) : IEntitySeeder
    where TEntity : EntityBase, IAggregateRoot
{
    private readonly ILogger _logger = provider.GetLogger<EntitySeederBase<TEntity>>();

    /// <summary>
    /// 初始化种子数据
    /// </summary>
    /// <returns></returns>
    public Task SeedAsync()
    {
        return provider.ExecuteScopedWorkAsync(async scopedProvider =>
        {
            var entities = await SeedDataAsync(scopedProvider);
            await SyncToDatabaseAsync(scopedProvider, entities);
        });
    }

    /// <summary>
    /// 重写以提供要初始化的种子数据
    /// </summary>
    /// <param name="scopedProvider"></param>
    /// <returns></returns>
    protected abstract Task<TEntity[]> SeedDataAsync(IServiceProvider scopedProvider);

    protected abstract ISpecification<TEntity> ExistingSpecification(TEntity entity);

    protected virtual async Task SyncToDatabaseAsync(IServiceProvider scopedProvider, TEntity[] entities)
    {
        if (entities.IsNullOrEmpty())
        {
            return;
        }

        var uow = scopedProvider.GetUnitOfWork(true);
        var repository = scopedProvider.GetRepository<TEntity>();
        foreach (var entity in entities)
        {
            var spec = ExistingSpecification(entity);
            var exist = await repository.AnyAsync(spec);
            if (exist)
            {
                continue;
            }

            await repository.InsertAsync(entity);
        }

        await uow.CommitAsync();
    }
}
